<template>
    <div style="width: 30px; margin: 0 auto">
        <el-popover placement="right" :width="400" trigger="click" :hide-after="0">
            <template #reference>
                <component is="PlusCircleOutlined" class="plusClass" ref="currentPlus"/>
            </template>
            <el-row :gutter="20">
                <el-col :span="8" class="colSpanClass" @click="addNode('YwuExecutorNode')"><span ><component is="UserOutlined"/> 执行人</span></el-col>
                <el-col :span="8" class="colSpanClass" @click="addNode('YwuApprovalNode')"><span ><component is="UserOutlined"/> 审批人</span></el-col>
                <el-col :span="8" class="colSpanClass" @click="addNode('YwuServiceNode')"><span ><component is="DatabaseOutlined"/> 服务节点</span></el-col>
            </el-row>

            <el-row :gutter="20">
                <el-col :span="8" class="colSpanClass" @click="addNode('YwuConditionalNode')"><span ><component is="ApartmentOutlined"/> 条件分支</span></el-col>
                <el-col :span="8" class="colSpanClass" @click="addNode('YwuParallelNode')"><span ><component is="BranchesOutlined"/> 并行分支</span></el-col>
            </el-row>
        </el-popover>
    </div>

    <div style="height: 30px"></div>

    <div style="width: 150px; margin: 0 auto" ref="currentDiv" @click="showDrawer()" @mouseenter="mouseEnter()" @mouseleave="mouseLeave()">
        <div class="conditionClass" ref="childRef">
            <div class="innerClass" style="padding-top: 10px;position: relative;">
                <component is="CloseCircleOutlined" class="closeClass" v-if="closeShow" @click="deleteNode()"/>
                <component is="ApartmentOutlined"/>
                <span class="spanClass">{{jsonInfo.name}}</span> <br />
                <span class="spanNameClass">{{jsonInfo.properties.name}}</span>
            </div>
        </div>
    </div>

    <div style="height: 30px"></div>

    <div style="width: 30px; margin: 0 auto">
        <component is="PlusCircleOutlined" class="plusClass" ref="addChildNodePlus" @click="addChildNodePlusFunc()"/>
    </div>

    <div style="height: 60px"></div>

    <div :style="calcChildrenWidth">
        <div v-for="(item, index) in jsonInfo.childrenNodes" :key="index" style=" display: inline-block;vertical-align: top;" :style="index !== 0 ? 'margin-left: 100px;' : ''">
            <div style="margin: 0 auto; width: 150px">
                <div class="conditionItemClass" :ref="(el) => {const refKey = `childNode${index}`;childNodeRefs[refKey]=el}" :id="'childNode' + index" @mouseenter="conditionMouseEnter(item, index)" @mouseleave="conditionMouseLeave(item)">
                    <div class="innerClass" style="padding-top: 10px;position: relative;">
                        <component is="CloseCircleOutlined" class="closeClass" v-if="item.isShow" @click="deleteCondition(item, index)"/>
                        <component is="ApartmentOutlined"/>
                        <span class="spanClass">{{item.conditionName}}</span>
                    </div>
                </div>
            </div>
            <svg width="100000px" height="100000px" style="position: absolute;z-index: -1; top: 0; left: 0;">
                <line :x1="currentChildListTopX[index]"
                      :y1="currentChildListTopY[index] - 40"
                      :x2="currentChildListTopX[index]"
                      :y2="currentChildListTopY[index] - 10"
                      stroke="#000" stroke-width="2" marker-end="url(#arrow)" />
            </svg>
            <div style="height: 30px"></div>

            <component v-if="item.next !== null && item.next" :is="item.next['type']" :jsonInfo="item.next" :beforeNode="item" :ref="(el) => {const refKey = `childComponentRef${index}`;childComponentRefs[refKey]=el}"
                       :beforeNodeStartX="currentChildListBottomX[index]" :beforeNodeStartY="currentChildListBottomY[index]" :globalJson="globalJson"></component>

            <div style="width: 30px; margin: 0 auto;">
                <el-popover placement="right" :width="400" trigger="click" :hide-after="0">
                    <template #reference>
                        <component is="PlusCircleOutlined" class="plusClass" :ref="(el) => {const refKey = `conditionLastPlus${index}`;conditionLastPlusRefs[refKey]=el}"/>
                    </template>
                    <el-row :gutter="20">
                        <el-col :span="8" class="colSpanClass" @click="addChildItemNodePlus('YwuExecutorNode', item)"><span ><component is="UserOutlined"/> 执行人</span></el-col>
                        <el-col :span="8" class="colSpanClass" @click="addChildItemNodePlus('YwuApprovalNode', item)"><span ><component is="UserOutlined"/> 审批人</span></el-col>
                        <el-col :span="8" class="colSpanClass" @click="addChildItemNodePlus('YwuServiceNode', item)"><span ><component is="DatabaseOutlined"/> 服务节点</span></el-col>
                    </el-row>

                    <el-row :gutter="20">
                        <el-col :span="8" class="colSpanClass" @click="addChildItemNodePlus('YwuConditionalNode', item)"><span ><component is="ApartmentOutlined"/> 条件分支</span></el-col>
                        <el-col :span="8" class="colSpanClass" @click="addChildItemNodePlus('YwuParallelNode', item)"><span ><component is="BranchesOutlined"/> 并行分支</span></el-col>
                    </el-row>
                </el-popover>
            </div>

            <svg width="100000px" height="100000px" style="position: absolute;z-index: -1; top: 0; left: 0;">
                <line :x1="lastComponentBottomX[index]"
                      :y1="lastComponentBottomY[index]"
                      :x2="conditionLastPlusTopX[index]"
                      :y2="conditionLastPlusTopY[index]"
                      stroke="#000" stroke-width="2" />
            </svg>
            <svg width="100000px" height="100000px" style="position: absolute;z-index: -1; top: 0; left: 0;">
                <line :x1="conditionLastPlusBottomX[index]"
                      :y1="conditionLastPlusBottomY[index]"
                      :x2="conditionLastPlusBottomX[index]"
                      :y2="realBottomY"
                      stroke="#000" stroke-width="2" />
            </svg>
        </div>
    </div>

    <div style="height: 60px"></div>

    <component v-if="jsonInfo.next !== null && jsonInfo.next" :is="jsonInfo.next['type']" :jsonInfo="jsonInfo.next" ref="commonChildRef"
               :beforeNode="jsonInfo" :beforeNodeStartX="realBottomX" :beforeNodeStartY="realBottomY" :globalJson="globalJson" :flowDetailJson="flowDetailJson"></component>

    <svg width="0" height="0">
        <defs>
            <marker id="arrow" markerWidth="6" markerHeight="6" refX="0" refY="2" orient="auto">
                <path d="M0,0 L0,4 L6,2 z" fill="#000000" />
            </marker>
        </defs>
    </svg>

    <svg width="100000px" height="100000px" style="position: absolute;z-index: -1; top: 0; left: 0;">
        <line :x1="beforeNodeStartX"
              :y1="beforeNodeStartY"
              :x2="currentPlusTopX"
              :y2="currentPlusTopY"
              stroke="#000" stroke-width="2" />
    </svg>

    <svg width="100000px" height="100000px" style="position: absolute;z-index: -1; top: 0; left: 0;">
        <line :x1="currentPlusBottomX"
              :y1="currentPlusBottomY"
              :x2="currentTopX"
              :y2="currentTopY"
              stroke="#000" stroke-width="2" marker-end="url(#arrow)" />
    </svg>

    <svg width="100000px" height="100000px" style="position: absolute;z-index: -1; top: 0; left: 0;">
        <line :x1="currentBottomX"
              :y1="currentBottomY"
              :x2="currentAddChildPlusTopX"
              :y2="currentAddChildPlusTopY"
              stroke="#000" stroke-width="2"/>
    </svg>

    <svg width="100000px" height="100000px" style="position: absolute;z-index: -1; top: 0; left: 0;">
        <line :x1="currentAddChildPlusBottomX"
              :y1="currentAddChildPlusBottomY"
              :x2="currentAddChildPlusBottomX"
              :y2="currentAddChildPlusBottomY + 20"
              stroke="#000" stroke-width="2"/>
    </svg>

    <svg width="100000px" height="100000px" style="position: absolute;z-index: -1; top: 0; left: 0;">
        <line :x1="conditionLastPlusBottomX[0]"
              :y1="realBottomY"
              :x2="conditionLastPlusBottomX[jsonInfo.childrenNodes.length - 1]"
              :y2="realBottomY"
              stroke="#000" stroke-width="2" />
    </svg>

    <svg width="100000px" height="100000px" style="position: absolute;z-index: -1; top: 0; left: 0;">
        <line :x1="currentChildListTopX[0]"
              :y1="currentChildListTopY[0] - 40"
              :x2="currentChildListTopX[jsonInfo.childrenNodes.length - 1]"
              :y2="currentChildListTopY[jsonInfo.childrenNodes.length - 1] - 40"
              stroke="#000" stroke-width="2" />
    </svg>

    <el-drawer v-model="drawerFlag" :with-header="false" :close-on-click-modal="false" :lock-scroll="true">
        <YwuConditionalNodeDrawer :properties="jsonInfo.properties"/>
        <template #footer>
            <div style="flex: auto">
                <el-button @click="cancelUpdate()">取消</el-button>
                <el-button type="primary" @click="confirmUpdate()">确认</el-button>
            </div>
        </template>
    </el-drawer>

    <el-drawer v-model="childNodeDrawerFlag" :with-header="false" :close-on-click-modal="false" :lock-scroll="true">
        <YwuConditionChildNodeDrawer :properties="jsonInfo.properties" :globalFlowInfo="globalJson"/>
        <template #footer>
            <div style="flex: auto">
                <el-button @click="cancelChildUpdate()">取消</el-button>
                <el-button type="primary" @click="confirmChildUpdate()">确认</el-button>
            </div>
        </template>
    </el-drawer>
</template>

<script name="YwuConditionalNode" setup>
import {addNodeInfo, getMaxWidth, parseMultiInfo} from "@/utils/flowCommon";
import emitter from '@/utils/mitt';
import YwuConditionalNodeDrawer from "@/views/bpmn/flow/drawer/YwuConditionalNodeDrawer.vue";
import YwuConditionChildNodeDrawer from "@/views/bpmn/flow/drawer/YwuConditionChildNodeDrawer.vue";
import {computed, onMounted, ref, nextTick, onBeforeUnmount} from "vue";

let props = defineProps(["jsonInfo", "beforeNodeStartX", "beforeNodeStartY", "beforeNode", "globalJson", "flowDetailJson"])

let jsonInfo = computed(() => {return props["jsonInfo"]});
let beforeNodeStartX = computed(() => {return props["beforeNodeStartX"]});
let beforeNodeStartY = computed(() => {return props["beforeNodeStartY"]});
let beforeNode = computed(() => {return props["beforeNode"]});
let globalJson = computed(() => {return props["globalJson"]});
let flowDetailJson = computed(() => {return props["flowDetailJson"]});

let currentTopX = ref(0);
let currentTopY = ref(0);
let currentBottomX = ref(0);
let currentBottomY = ref(0);
let realBottomX = ref(0);
let realBottomY = ref(0);
let currentPlusTopX = ref(0);
let currentPlusTopY = ref(0);
let currentPlusBottomX = ref(0);
let currentPlusBottomY = ref(0);
let currentAddChildPlusTopX = ref(0);
let currentAddChildPlusTopY = ref(0);
let currentAddChildPlusBottomX = ref(0);
let currentAddChildPlusBottomY = ref(0);
let currentChildListTopX = ref([]);
let currentChildListTopY = ref([]);
let currentChildListBottomX = ref([]);
let currentChildListBottomY = ref([]);
let lastComponentBottomX = ref([]);
let lastComponentBottomY = ref([]);
let conditionLastPlusTopX = ref([]);
let conditionLastPlusTopY = ref([]);
let conditionLastPlusBottomX = ref([]);
let conditionLastPlusBottomY = ref([]);
let closeShow = ref(false);
let isDelete = ref(false);
let drawerFlag = ref(false);
let propertiesCopy = ref({});
let childNodeDrawerFlag = ref(false);

let commonChildRef = ref(null);

let calcChildrenWidth = computed(() => {
    let res = "margin: 0 auto;"
    if (jsonInfo.value.childrenNodes.length > 0) {
        let width = jsonInfo.value.width * 150 + 100 * (jsonInfo.value.width - 1);
        res += "width :" + width + "px";
    }
    return res;
});

onMounted(() => {
    nextTick(() => {
        calcXy();
    });
    // 在组件挂载时添加窗口大小改变的监听器
    window.addEventListener('resize', calcXy);
    // 接收事件
    emitter.on('refreshLine', (message) => {
        nextTick(() => {
            calcXy();
        });
    });
})

onBeforeUnmount(() => {
    // 在组件销毁前移除监听器，避免内存泄漏
    window.removeEventListener('resize', calcXy);
})

let currentDiv = ref(null);
let currentPlus = ref(null);
let addChildNodePlus = ref(null);

let childNodeRefs = ref({});
let conditionLastPlusRefs = ref({});
let childComponentRefs = ref({});

function calcXy() {
    if (isDelete.value) {
        return;
    }
    realBottomY.value = 0;
    let nodeInfo = currentDiv.value;
    currentTopX.value = nodeInfo.offsetLeft + nodeInfo.offsetWidth / 2;
    currentBottomX.value = nodeInfo.offsetLeft + nodeInfo.offsetWidth / 2;
    currentTopY.value = nodeInfo.offsetTop - 10;
    currentBottomY.value = nodeInfo.offsetTop + nodeInfo.offsetHeight;
    nodeInfo = currentPlus.value;
    currentPlusTopX.value = nodeInfo.offsetLeft + nodeInfo.offsetWidth / 2;
    currentPlusBottomX.value = nodeInfo.offsetLeft + nodeInfo.offsetWidth / 2;
    currentPlusTopY.value = nodeInfo.offsetTop;
    currentPlusBottomY.value = nodeInfo.offsetTop + nodeInfo.offsetHeight;
    nodeInfo = addChildNodePlus.value;
    currentAddChildPlusTopX.value = nodeInfo.offsetLeft + nodeInfo.offsetWidth / 2;
    currentAddChildPlusBottomX.value = nodeInfo.offsetLeft + nodeInfo.offsetWidth / 2;
    currentAddChildPlusTopY.value = nodeInfo.offsetTop;
    currentAddChildPlusBottomY.value = nodeInfo.offsetTop + nodeInfo.offsetHeight;
    // 解析所有子分支节点的位置信息
    for (let index = 0; index < jsonInfo.value.childrenNodes.length; index++) {
        let tempNodeInfo = childNodeRefs.value['childNode' + index];
        currentChildListTopX.value[index] = tempNodeInfo.offsetLeft + tempNodeInfo.offsetWidth / 2;
        currentChildListTopY.value[index] = tempNodeInfo.offsetTop;
        currentChildListBottomX.value[index] = tempNodeInfo.offsetLeft + tempNodeInfo.offsetWidth / 2;
        currentChildListBottomY.value[index] = tempNodeInfo.offsetTop + tempNodeInfo.offsetHeight;
    }
    // 获取当前分支下的最深处子结点的位置信息
    for (let index = 0; index < jsonInfo.value.childrenNodes.length; index++) {
        nodeInfo = conditionLastPlusRefs.value['conditionLastPlus' + index];
        conditionLastPlusTopX.value[index] = nodeInfo.offsetLeft + nodeInfo.offsetWidth / 2;
        conditionLastPlusBottomX.value[index] = nodeInfo.offsetLeft + nodeInfo.offsetWidth / 2;
        conditionLastPlusTopY.value[index] = nodeInfo.offsetTop;
        conditionLastPlusBottomY.value[index] = nodeInfo.offsetTop + nodeInfo.offsetHeight;
        let item = jsonInfo.value.childrenNodes[index];
        realBottomY.value = realBottomY.value > conditionLastPlusBottomY.value[index] ? realBottomY.value : conditionLastPlusBottomY.value[index] + 30
        if (!item.next) {
            // 没有挂载其他结点
            lastComponentBottomX.value[index] = currentChildListBottomX.value[index];
            lastComponentBottomY.value[index] = currentChildListBottomY.value[index];
        } else {
            let tempChildRef = childComponentRefs.value['childComponentRef' + index];
            // 递归往下获取
            while (true) {
                if (!tempChildRef.jsonInfo.next) {
                    tempChildRef.calcXy();
                    lastComponentBottomX.value[index] = tempChildRef.realBottomX;
                    lastComponentBottomY.value[index] = tempChildRef.realBottomY;
                    break;
                }
                tempChildRef = tempChildRef['commonChildRef']
            }
        }
    }
    realBottomX.value = currentPlusTopX.value
}

function addNode(nodeType) {
    addNodeInfo(nodeType, beforeNode.value, jsonInfo.value, globalJson.value);
    emitter.emit("refreshLine", "refreshLine");
}

function mouseEnter() {
    closeShow.value = true
}

function mouseLeave() {
    closeShow.value = false;
}

function conditionMouseEnter(item, index) {
    if (index !== jsonInfo.value.childrenNodes.length - 1 || jsonInfo.value.childrenNodes.length > 2) {
        item.isShow = true;
    }
}

function conditionMouseLeave(item) {
    item.isShow = false;
}

function deleteNode() {
    isDelete.value = true;
    beforeNode.value.next = jsonInfo.value.next;
    parseMultiInfo(globalJson.value);
    getMaxWidth(globalJson.value);
    emitter.emit("refreshLine", "refreshLine");
}

function deleteCondition(item, index) {
    if (index === jsonInfo.value.childrenNodes.length - 1 || jsonInfo.value.childrenNodes.length <= 2) {
        return;
    }
    // 删除当前分支
    jsonInfo.value.childrenNodes.splice(index, 1);
    // 重新设置名称
    for (let index = 0; index < jsonInfo.value.childrenNodes.length; index++) {
        let info = jsonInfo.value.childrenNodes[index];
        if (index !== jsonInfo.value.childrenNodes.length - 1) {
            info.conditionName = "条件" + (index + 1);
        } else {
            info.conditionName = "其他条件";
        }
    }
    parseMultiInfo(globalJson.value);
    getMaxWidth(globalJson.value);
    emitter.emit("refreshLine", "refreshLine");
}

function addChildNodePlusFunc() {
    let info = {
        type: "common",
        conditionName: "条件" + jsonInfo.value.childrenNodes.length,
        condition: {}
    }
    jsonInfo.value.childrenNodes.splice(jsonInfo.value.childrenNodes.length - 1, 0, info)
    parseMultiInfo(globalJson.value);
    getMaxWidth(globalJson.value);
    emitter.emit("refreshLine", "refreshLine");
}

function addChildItemNodePlus(nodeType, item) {
    if (item.next) {
        // 遍历到最后一个结点
        let lastNode = item.next
        while (true) {
            if (!lastNode.next) {
                break;
            }
            lastNode = lastNode.next
        }
        addNodeInfo(nodeType, lastNode, null, globalJson.value);
    } else {
        addNodeInfo(nodeType, item, null, globalJson.value);
    }
    emitter.emit("refreshLine", "refreshLine");
}

function showDrawer() {
    // 备份数据
    propertiesCopy.value = {...jsonInfo.value.properties}
    drawerFlag.value = true
}

function confirmUpdate() {
    drawerFlag.value = false;
}

function cancelUpdate() {
    drawerFlag.value = false;
    // 还原数据
    jsonInfo.value.properties = {...propertiesCopy.value};
}

function cancelChildUpdate() {

}

function confirmChildUpdate() {

}

defineExpose({
    jsonInfo, calcXy, commonChildRef, realBottomX, realBottomY
})

</script>

<style scoped lang="less">
.conditionClass {
    width: 150px;
    height: 80px;
    background-color: rgba(191, 0, 255, 0.4);
    border-radius: 10px;
    .innerClass {
        margin-left: 10px;
        .spanClass {
            margin-left: 10px;
            font-weight: bold;
        }
    }
}
.conditionClass:hover{
    cursor: pointer;
}

.plusClass {
    font-size: 30px;
}

.plusClass:hover {
    cursor: pointer;
    color: rgba(4, 85, 248, 0.91);
}

.spanNameClass {
    margin-top: 10px;
    display: inline-block;
    width: 140px;
    overflow: hidden;
    white-space: nowrap;
    text-overflow: ellipsis;
    line-height: 13px;
    font-size: 13px;
}

.colSpanClass{
    height: 50px;
    font-size: 20px;
    line-height: 50px;
}

.colSpanClass:hover {
    background-color: #dfe4e7;
    cursor: pointer;
}

.closeClass {
    position: absolute;
    top: 10px;
    right: 10px;
    font-size: 15px;
}

.closeClass:hover {
    color: #ee4646;
}

.conditionItemClass {
    display: inline-block;
    vertical-align: top;
    width: 150px;
    margin: 0 auto;
    height: 80px;
    background-color: rgba(191, 0, 255, 0.4);
    border-radius: 10px;
    .innerClass {
        margin-left: 10px;
        .spanClass {
            margin-left: 10px;
            font-weight: bold;
        }
    }
}

.conditionItemClass {
    cursor: pointer;
}
</style>